<!-- 大屏自适应容器组件 需固定宽高 否者按照 1920*1080 处理-->
<template>
	<!-- <section class="screen-box" :style="boxStyle"> -->
	<div class="screen-wrapper" ref="screenWrapper" :style="wrapperStyle">
		<slot></slot>
	</div>
	<!-- </section> -->
</template>
<script>
/**
 * 防抖函数
 * @param {T} fn
 * @param {number} delay
 * @return
 */
function debounce(fn, delay) {
	let timer = null;
	return function (...args) {
		timer = setTimeout(
			() => {
				typeof fn === "function" && fn.apply(null, args);
				clearTimeout(timer);
			},
			delay > 0 ? delay : 100
		);
	};
}

export default {
	name: "VScaleScreen",
	props: {
		// 大屏宽度
		width: {
			type: [String, Number],
			default: 1920,
		},
		// 大屏高度
		height: {
			type: [String, Number],
			default: 1080,
		},
		// 全屏自适应，启用此配置项时会存在拉伸效果，同时autoScale失效，非必要情况下不建议开启
		fullScreen: {
			type: Boolean,
			default: false,
		},
		// 自适应配置，配置为boolean类型时，为启动或者关闭自适应，配置为对象时，若x为true，x轴产生边距，y为true时，y轴产生边距，启用fullScreen时此配置失效 | Boolean or {x:boolean,y:boolean}
		autoScale: {
			type: [Object, Boolean],
			default: true,
		},
		//是否进行自适应
		selfAdaption: {
			type: Boolean,
			default: true,
		},
		// 窗口变化防抖延迟时间
		delay: {
			type: Number,
			default: 500,
		},
		// 修改容器样式，如居中展示时侧边背景色，符合Vue双向绑定style标准格式
		boxStyle: {
			type: Object,
			default: () => ({}),
		},
		// 修改自适应区域样式，符合Vue双向绑定style标准格式
		wrapperStyle: {
			type: Object,
			default: () => ({}),
		},
	},
	data() {
		return {
			currentWidth: 0,
			currentHeight: 0,
			originalWidth: 0,
			originalHeight: 0,
			onResize: null,
			observer: null,
		};
	},
	watch: {
		//是否进行自适应判断
		selfAdaption(val) {
			// 如果自适应，设置并初始化自适应，添加监听事件
			if (val) {
				this.resize();
				this.addListener();
			} else {
				// 否者清除所有样式，并移除监听事件
				this.clearListener();
				this.clearStyle();
			}
		},
	},
	computed: {
		screenWrapper() {
			return this.$refs["screenWrapper"];
		},
	},
	methods: {
		initSize() {
			return new Promise((resolve, reject) => {
				// console.log("初始化样式");
				//给父元素设置 overflow:hidden
				this.screenWrapper.parentNode.style.overflow = "hidden";
				this.screenWrapper.parentNode.scrollLeft = 0;
				this.screenWrapper.parentNode.scrollTop = 0;

				this.$nextTick(() => {
					// region 获取大屏真实尺寸
					if (this.width && this.height) {
						this.currentWidth = this.width;
						this.currentHeight = this.height;
					} else {
						this.currentWidth = this.screenWrapper.clientWidth;
						this.currentHeight = this.screenWrapper.clientHeight;
					}
					// endregion
					// region 获取画布尺寸
					if (!this.originalHeight || !this.originalWidth) {
						this.originalWidth = window.screen.width;
						this.originalHeight = window.screen.height;
					}
					// endregion
					resolve();
				});
			});
		},
		updateSize() {
			if (this.currentWidth && this.currentHeight) {
				this.screenWrapper.style.width = `${this.currentWidth}px`;
				this.screenWrapper.style.height = `${this.currentHeight}px`;
			} else {
				this.screenWrapper.style.width = `${this.originalWidth}px`;
				this.screenWrapper.style.height = `${this.originalHeight}px`;
			}
		},
		handleAutoScale(scale) {
			if (!this.autoScale) return;
			const screenWrapper = this.screenWrapper;
			const domWidth = screenWrapper.clientWidth;
			const domHeight = screenWrapper.clientHeight;
			const currentWidth = document.body.clientWidth;
			const currentHeight = document.body.clientHeight;
			screenWrapper.style.transform = `scale(${scale},${scale}) `;
			let mx = Math.max((currentWidth - domWidth * scale) / 2, 0);
			let my = Math.max((currentHeight - domHeight * scale) / 2, 0);
			if (typeof this.autoScale === "object") {
				// @ts-ignore
				!this.autoScale.x && (mx = 0);
				// @ts-ignore
				!this.autoScale.y && (my = 0);
			}
			// console.log({
			//   mx,
			//   my,
			//   currentWidth,
			//   currentHeight,
			//   domWidth,
			//   domHeight,
			//   scale,
			// });
			this.screenWrapper.style.margin = `${my}px ${mx}px`;
		},
		updateScale() {
			const screenWrapper = this.screenWrapper;
			// 获取真实视口尺寸
			const currentWidth = document.body.clientWidth;
			const currentHeight = document.body.clientHeight;
			// 获取大屏最终的宽高onResize
			const realWidth = this.currentWidth || this.originalWidth;
			const realHeight = this.currentHeight || this.originalHeight;
			// 计算缩放比例
			const widthScale = currentWidth / realWidth;
			const heightScale = currentHeight / realHeight;
			// console.log({currentWidth, currentHeight,realWidth,realHeight});

			// 若要铺满全屏，则按照各自比例缩放
			if (this.fullScreen) {
				screenWrapper.style.transform = `scale(${widthScale},${heightScale})`;
				return false;
			}
			// 按照宽高最小比例进行缩放
			const scale = Math.min(widthScale, heightScale);
			this.handleAutoScale(scale);
		},
		initMutationObserver() {
			const screenWrapper = this.screenWrapper;
			const observer = (this.observer = new MutationObserver(() => {
				this.onResize();
			}));

			observer.observe(screenWrapper, {
				attributes: true,
				attributeFilter: ["style"],
				attributeOldValue: true,
			});
		},
		/**
		 * @description 添加监听事件
		 */
		addListener() {
			window.addEventListener("resize", this.onResize);
		},
		/**
		 * @description 移除监听事件
		 */
		clearListener() {
			window.removeEventListener("resize", this.onResize);
		},
		/**
		 * @description 清除样式
		 */
		clearStyle() {
			// console.log("清除");
			const screenWrapper = this.screenWrapper;
			screenWrapper.parentNode.style.overflow = "auto";

			screenWrapper.style = "";
		},
		/**
		 * @description 初始化并设置自适应
		 */
		async resize() {
			if (!this.selfAdaption) {
				return;
			}
			await this.initSize();
			this.updateSize();
			this.updateScale();
		},
	},
	mounted() {
		this.onResize = debounce(() => {
			this.resize();
		}, this.delay);
		this.$nextTick(() => {
			if (this.selfAdaption) {
				this.resize();
				this.addListener();
			}
		});
	},
	beforeDestroy() {
		this.clearListener();
		// this.observer.disconnect()
	},
};
//
</script>

<style scoped lang="scss">
.screen-box {
	overflow: hidden;
	background-size: 100% 100%;
	background: #000;
	width: 100vw;
	height: 100vh;
}

.screen-wrapper {
	transition-property: all;
	transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	transition-duration: 500ms;
	position: relative;
	overflow: hidden;
	z-index: 100;
	transform-origin: left top;
}
</style>
